home *** CD-ROM | disk | FTP | other *** search
- /* TTY device functions.
- Copyright (C) 1994, 1995 Board of Trustees, University of Illinois
- Copyright (C) 1994, 1995 Amdahl Corporation
-
- This file is part of XEmacs.
-
- XEmacs is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- XEmacs is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with XEmacs; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Synched up with: Not in FSF. */
-
- /* Authors: Chuck Thompson and Ben Wing. */
-
- #include <config.h>
- #include "lisp.h"
-
- #include "device-tty.h"
- #include "device-stream.h"
- #include "events.h"
- #include "faces.h"
- #include "frame.h"
- #include "redisplay.h"
- #include "sysdep.h"
-
- #include "syssignal.h" /* for SIGWINCH */
-
- #include <errno.h>
-
- DEFINE_DEVICE_TYPE (tty);
-
- Lisp_Object Qterminal_type;
-
-
- static void
- allocate_tty_device_struct (struct device *d)
- {
- d->device_data =
- (struct tty_device *) xmalloc (sizeof (struct tty_device));
-
- /* zero out all slots. */
- memset (d->device_data, 0, sizeof (struct tty_device));
- /* except the lisp ones ... */
- DEVICE_TTY_DATA (d)->tty = Qnil;
- DEVICE_TTY_DATA (d)->terminal_type = Qnil;
- }
-
- static void
- tty_init_device (struct device *d, Lisp_Object params)
- {
- Lisp_Object tty = Qnil, terminal_type = Qnil;
- FILE *infd, *outfd;
-
- tty = Fcdr_safe (Fassq (Qtty, params));
- terminal_type = Fcdr_safe (Fassq (Qterminal_type, params));
-
- /* Open the specified device */
-
- if (NILP (tty))
- {
- infd = stdin;
- outfd = stdout;
- }
- else
- {
- CHECK_STRING (tty, 0);
- infd = outfd = fopen ((char *) string_data (XSTRING (tty)), "r+");
- if (!infd)
- error ("Unable to open tty %s", string_data (XSTRING (tty)));
- }
-
- /* Determine the terminal type */
-
- if (!NILP (terminal_type))
- CHECK_STRING (terminal_type, 0);
- else
- {
- char *temp_type = (char *) getenv ("TERM");
-
- if (!temp_type)
- {
- if (infd != stdin)
- fclose (infd);
- error ("Cannot determine terminal type");
- }
- else
- terminal_type = build_string (temp_type);
- }
-
- allocate_tty_device_struct (d);
- DEVICE_TTY_DATA (d)->infd = infd;
- DEVICE_TTY_DATA (d)->outfd = outfd;
- DEVICE_TTY_DATA (d)->terminal_type = terminal_type;
- if (NILP (tty))
- tty = build_string ("stdio");
- DEVICE_TTY_DATA (d)->tty = tty;
- if (NILP (DEVICE_NAME (d)))
- DEVICE_NAME (d) = Ffile_name_nondirectory (tty);
- DEVICE_INFD (d) = fileno (infd);
- DEVICE_OUTFD (d) = fileno (outfd);
- {
- int tty_pg;
- int controlling_tty_pg;
- int cfd;
-
- /* OK, the only sure-fire way I can think of to determine
- whether a particular TTY is our controlling TTY is to check
- if it has the same foreground process group as our controlling
- TTY. This is OK because a process group can never simultaneously
- be the foreground process group of two TTY's (in that case it
- would have two controlling TTY's, which is not allowed). */
-
- EMACS_GET_TTY_PROCESS_GROUP (fileno (infd), &tty_pg);
- cfd = open ("/dev/tty", O_RDWR, 0);
- EMACS_GET_TTY_PROCESS_GROUP (cfd, &controlling_tty_pg);
- close (cfd);
- if (tty_pg == controlling_tty_pg)
- {
- DEVICE_TTY_DATA (d)->controlling_terminal = 1;
- XSETDEVICE (Vcontrolling_terminal, d);
- munge_tty_process_group ();
- }
- else
- DEVICE_TTY_DATA (d)->controlling_terminal = 0;
- }
-
- init_baud_rate (d);
-
- switch (init_tty_for_redisplay
- (d, (char *) string_data (XSTRING (terminal_type))))
- {
- case TTY_UNABLE_OPEN_DATABASE:
- error ("Can't access terminal information database");
- break;
- case TTY_TYPE_UNDEFINED:
- error ("Terminal type `%s' undefined",
- string_data (XSTRING (terminal_type)));
- break;
- case TTY_TYPE_INSUFFICIENT:
- error ("Terminal type `%s' not powerful enough to run Emacs",
- string_data (XSTRING (terminal_type)));
- break;
- case TTY_SIZE_UNSPECIFIED:
- error ("Can't determine window size of terminal");
- break;
- case TTY_INIT_SUCCESS:
- break;
- default:
- abort ();
- }
-
- init_one_device (d);
-
- /* This will cause the elisp side of the TTY device intialization to
- be loaded. At this point we consider the two parts to be one.
- They are split up because of requirements in lisp/prim/startup.el */
- Frequire (intern ("pre-tty-win"), Qnil);
- Frequire (intern ("post-tty-win"), Qnil);
- }
-
- static void
- tty_mark_device (struct device *d, void (*markobj) (Lisp_Object))
- {
- ((markobj) (DEVICE_TTY_DATA (d)->tty));
- ((markobj) (DEVICE_TTY_DATA (d)->terminal_type));
- }
-
-
- static int
- tty_initially_selected_for_input (struct device *d)
- {
- return 1;
- }
-
- static void
- free_tty_device_struct (struct device *d)
- {
- struct tty_device *td = (struct tty_device *) d->device_data;
- if (td && td->term_entry_buffer) /* allocated in term_init () */
- xfree (td->term_entry_buffer);
- if (td)
- xfree (td);
- }
-
- static void
- tty_delete_device (struct device *d)
- {
- if (DEVICE_TTY_DATA (d)->infd != stdin)
- fclose (DEVICE_TTY_DATA (d)->infd);
- if (DEVICE_TTY_DATA (d)->controlling_terminal)
- {
- Vcontrolling_terminal = Qnil;
- unmunge_tty_process_group ();
- }
- free_tty_device_struct (d);
- }
-
- #ifdef SIGWINCH
-
- static SIGTYPE
- tty_device_size_change_signal (int signo)
- {
- int old_errno = errno;
- asynch_device_change_pending++;
- signal_fake_event ();
- EMACS_REESTABLISH_SIGNAL (SIGWINCH, tty_device_size_change_signal);
- errno = old_errno;
- SIGRETURN;
- }
-
- /* frame_change_signal does nothing but set a flag that it was called.
- When redisplay is called, it will notice that the flag is set and
- call handle_pending_device_size_change to do the actual work. */
- static void
- tty_asynch_device_change (void)
- {
- Lisp_Object device;
-
- for (device = Vdevice_list ; !NILP (device) ; device = XCDR (device))
- {
- int width, height;
- Lisp_Object tail;
- struct device *d = XDEVICE (XCAR (device));
-
- if (!DEVICE_IS_TTY (d))
- continue;
-
- get_tty_device_size (d, &width, &height);
- if (width > 0 && height > 0)
- {
- DEVICE_TTY_DATA (d)->width = width;
- DEVICE_TTY_DATA (d)->height = height;
-
- for (tail = DEVICE_FRAME_LIST (d);
- !NILP (tail);
- tail = XCDR (tail))
- {
- struct frame *f = XFRAME (XCAR (tail));
-
- /* We know the frame is tty because we made sure that the
- device is tty. */
- change_frame_size (f, height, width, 0, 1);
- }
- }
- }
- }
-
- #endif /* SIGWINCH */
-
- static int
- tty_device_pixel_width (struct device *d)
- {
- return DEVICE_TTY_DATA (d)->width;
- }
-
- static int
- tty_device_pixel_height (struct device *d)
- {
- return DEVICE_TTY_DATA (d)->height;
- }
-
-
- static struct device *
- get_tty_device (Lisp_Object device)
- {
- if (NILP (device))
- device = Fselected_device ();
- /* quietly accept frames for the device arg */
- if (FRAMEP (device))
- device = XFRAME (device)->device;
- CHECK_TTY_DEVICE (device, 0);
- return XDEVICE (device);
- }
-
- DEFUN ("device-tty-tty", Fdevice_tty_tty, Sdevice_tty_tty, 0, 1, 0,
- "Return the tty filename which DEVICE is connected to, as a string.")
- (device)
- Lisp_Object device;
- {
- return DEVICE_TTY_DATA (get_tty_device (device))->tty;
- }
-
- DEFUN ("device-tty-terminal-type", Fdevice_tty_terminal_type,
- Sdevice_tty_terminal_type, 0, 1, 0,
- "Return the terminal type of TTY device DEVICE.")
- (device)
- Lisp_Object device;
- {
- return DEVICE_TTY_DATA (get_tty_device (device))->terminal_type;
- }
-
-
- /************************************************************************/
- /* initialization */
- /************************************************************************/
-
- void
- syms_of_device_tty (void)
- {
- defsubr (&Sdevice_tty_tty);
- defsubr (&Sdevice_tty_terminal_type);
- defsymbol (&Qterminal_type, "terminal-type");
- }
-
- void
- device_type_create_tty (void)
- {
- INITIALIZE_DEVICE_TYPE (tty, "tty", "device-tty-p");
-
- DEVICE_HAS_METHOD (tty, init_device);
- DEVICE_HAS_METHOD (tty, mark_device);
- DEVICE_HAS_METHOD (tty, initially_selected_for_input);
- DEVICE_HAS_METHOD (tty, delete_device);
- #ifdef SIGWINCH
- DEVICE_HAS_METHOD (tty, asynch_device_change);
- #endif /* SIGWINCH */
- DEVICE_HAS_METHOD (tty, device_pixel_width);
- DEVICE_HAS_METHOD (tty, device_pixel_height);
- }
-
- void
- vars_of_device_tty (void)
- {
- Fprovide (Qtty);
- }
-
- void
- init_device_tty (void)
- {
- #ifdef SIGWINCH
- if (initialized && !noninteractive)
- signal (SIGWINCH, tty_device_size_change_signal);
- #endif /* SIGWINCH */
- }
-